package ru.amse.tsyganov.jumleditor.view;

import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import ru.amse.tsyganov.jumleditor.model.ActivityGraph;
import ru.amse.tsyganov.jumleditor.model.State;
import ru.amse.tsyganov.jumleditor.model.Transition;
import ru.amse.tsyganov.jumleditor.properties.PropertiesList;
import ru.amse.tsyganov.jumleditor.properties.StringProperty;

public class ActivityGraphView<T extends ActivityGraph> extends ViewElement<T> {
	
	private static final int PRECISION_OF_SELECTION = 10;
	
	private final ModelViewMap modelViewMap = new ModelViewMap();
	
	private final SelectedItems selectedItems = new SelectedItems();
	
	public ActivityGraphView(T model) {
		super(model);
	}

	@Override
	public void accept(Visitor v) {
		v.visitActivityGraphView(this);
		
		for (State s : getModel().getContents()) {
			StateView<? extends State> stateView = 
				getModelViewMap().getStatesMap().get(s);
			stateView.accept(v);
		}
	}

	@Override
	public void paint(GC gc) {
		assert gc != null;
		
		gc.setAntialias(SWT.ON);
		gc.setFont(Fonts.getDefaultFont());
		
		for (StateView<? extends State> s : getModelViewMap().
				getStatesMap().values()) {
			
			s.prepaintEvent(gc);
		}
				
		for (State s : getModel().getContents()) {
			StateView<? extends State> stateView = 
				getModelViewMap().getStatesMap().get(s);
			stateView.paintTransitions(gc);
		}
		
		for (State s : getModel().getContents()) {
			StateView<? extends State> stateView = 
				getModelViewMap().getStatesMap().get(s);
			stateView.paint(gc);
		}
		
		paintActivePoints(gc);
	}

	@Override
	public List<? extends ActivePoint> getActivePoints() {
		throw new UnsupportedOperationException();
	}
	
	@Override
	public ModelViewMap getModelViewMap() {
		return modelViewMap;
	}
	
	@Override
	public SelectedItems getSelectedItems() {
		return selectedItems;
	}

	@Override
	public ActivityGraphView<T> getActivityGraphView() {
		return this;
	}
	
	public StateView<? extends State> getStateView(int x, int y) {

		for (State s : getModel().getContents()) {
			StateView<? extends State> stateView = getModelViewMap()
					.getStatesMap().get(s);
			if (stateView.getRectangle().contains(x, y)) {
				return stateView;
			}
		}
		return null;
	}
	
	public TransitionView<? extends Transition> getTransitionView(int x, int y) {

		for (State s : getModel().getContents()) {
			for (Transition t : s.getStateVertex().getOutgoing()) {

				State source = t.getSource().getContainer();
				State target = t.getTarget().getContainer();

				StateView<? extends State> sourceStateView = getModelViewMap()
						.getStatesMap().get(source);

				StateView<? extends State> targetStateView = getModelViewMap()
						.getStatesMap().get(target);

				int x0 = sourceStateView.getCenterPoint().x;
				int y0 = sourceStateView.getCenterPoint().y;

				int x1 = targetStateView.getCenterPoint().x;
				int y1 = targetStateView.getCenterPoint().y;

				double d = Math
						.abs(((y0 - y1) * x + (x1 - x0) * y + (x0 * y1 - x1
								* y0))
								/ Math.sqrt(Math.pow(x1 - x0, 2)
										+ Math.pow(y1 - y0, 2)));

				if (x0 > x1) {
					int b = x0;
					x0 = x1;
					x1 = b;
				}

				if (y0 > y1) {
					int b = y0;
					y0 = y1;
					y1 = b;
				}

				if (x >= (x0 - PRECISION_OF_SELECTION)
						&& x <= (x1 + PRECISION_OF_SELECTION)
						&& y >= (y0 - PRECISION_OF_SELECTION)
						&& y <= (y1 + PRECISION_OF_SELECTION)) {

					if (d < PRECISION_OF_SELECTION) {
						return getModelViewMap().getTransitionsMap().get(t);
					}
				}
			}
		}
		return null;
	}
	
	public ActivePoint getActivePoint(int x, int y) {

		for (State s : getModel().getContents()) {

			StateView<? extends State> stateView = getModelViewMap()
					.getStatesMap().get(s);

			for (ActivePoint point : stateView.getActivePoints()) {
				if (point.getRectangle().contains(x, y)) {
					return point;
				}
			}

			for (Transition t : s.getStateVertex().getOutgoing()) {
				TransitionView<? extends Transition> transitionView = 
					getModelViewMap().getTransitionsMap().get(t);

				for (ActivePoint point : transitionView.getActivePoints()) {
					if (point.getRectangle().contains(x, y)) {
						return point;
					}
				}
			}
		}
		return null;
	}

	@Override
	public void paintActivePoints(GC gc) {
		for (StateView<? extends State> s : 
			getSelectedItems().getSelectedStates()) {
			
			s.paintActivePoints(gc);
		}
		
		for (TransitionView<? extends Transition> t : 
			getSelectedItems().getSelectedTransitions()) {
			
			t.paintActivePoints(gc);
		}
	}
	
	@Override
	public PropertiesList getProperties() {
		throw new UnsupportedOperationException();
	}

	@Override
	public StringProperty getMainProperty() {
		throw new UnsupportedOperationException();
	}

	@Override
	public Point getCenterPoint() {
		throw new UnsupportedOperationException();
	}
	
	public void readFromXml(Node element) {
	}

	public void writeToXml(Element element) {
	}

}
